[FFmpeg-devel] [PATCH] avfilter/drawtext: special metadata fields to allow plotting source filename to output.

Alexandre Heitor Schmidt alexandre.schmidt at gmail.com
Sun Dec 15 00:59:31 EET 2019


avfilter/drawtext: Added two special metadata tags which can, be used by
'drawtext' filter and others to have access to source file path, and its
basename.

The new field AVPacket->source_file will contain a path to its corresponding
filename everytime the packet corresponds to a single file. This behavior is
common for image2 filter. When this field is filled, frames passed to filters
will contain two special metadata tags called source_path (the entire path to
the file) and source_basename (only the file name). These metatags can be
used by filters like drawtext to be able to plot the entire path or the
basename of it respectively to the frame being processed.

doc/filters: The documentation for drawtext was also updated and an usage
example was added.

Fixes #2874.

Signed-off-by: Alexandre Heitor Schmidt <alexandre.schmidt at gmail.com>
---
 doc/filters.texi      | 13 +++++++++++++
 fftools/ffmpeg.c      | 12 ++++++++++++
 libavcodec/avcodec.h  |  8 ++++++++
 libavcodec/avpacket.c |  1 +
 libavformat/img2dec.c |  9 +++++++++
 5 files changed, 43 insertions(+)

diff --git a/doc/filters.texi b/doc/filters.texi
index 93f54a2e1e..d984efb73b 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -9726,6 +9726,12 @@ printed by running @code{ffprobe -show_frames}.
 String metadata generated in filters leading to
 the drawtext filter are also available.
 
+There are two special metadata fields (@var{source_path} and @var{source_basename})
+which can be used when input format has a file corresponding to each frame, such
+as @var{image2}. @var{source_path} will output the entire path to the filename
+which generated the frame in question, while @var{source_basename} outputs the
+equivalent to @code{basename(source_path)}.
+
 @item n, frame_num
 The frame number, starting from 0.
 
@@ -9872,6 +9878,13 @@ drawtext=fontfile=FreeSans.ttf:text=DOG:fontsize=24:x=10:y=20+24-max_glyph_a,
 drawtext=fontfile=FreeSans.ttf:text=cow:fontsize=24:x=80:y=20+24-max_glyph_a
 @end example
 
+ at item
+Plot special @var{source_basename} metadata, extracted from each input frame, or
+the string "NA" if the metadata is not defined.
+ at example
+drawtext="fontsize=20:fontcolor=white:fontfile=FreeSans.ttf:text='%{metadata\:source_basename\:NA}':x=10:y=10"
+ at end example
+
 @end itemize
 
 For more information about libfreetype, check:
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 27f68933f8..9285f86a81 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -2375,6 +2375,18 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_
     if (ret < 0)
         *decode_failed = 1;
 
+    /**
+     * Set filename as a frame metadata, if it's not empty. This will allow filters
+     * like drawtext to use this information for cases like image2, where each frame
+     * corresponds to a file.
+     */
+    if (pkt) {
+        if ( pkt->source_filename != NULL ) {
+            av_dict_set(&decoded_frame->metadata, "source_path", pkt->source_filename, 0);
+            av_dict_set(&decoded_frame->metadata, "source_basename", av_basename(pkt->source_filename), 0);
+        }
+    }
+
     // The following line may be required in some cases where there is no parser
     // or the parser does not has_b_frames correctly
     if (ist->st->codecpar->video_delay < ist->dec_ctx->has_b_frames) {
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 119b32dc1f..4e285f4dd8 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1511,6 +1511,14 @@ typedef struct AVPacket {
     attribute_deprecated
     int64_t convergence_duration;
 #endif
+
+    /**
+     * In cases where the packet corresponds to the contents of one single
+     * file, like when image2 is used, this is set to the source filename,
+     * so it can be used by filters like drawtext, to plot the source
+     * filename on the frame.
+     */
+    char *source_filename;
 } AVPacket;
 #define AV_PKT_FLAG_KEY     0x0001 ///< The packet contains a keyframe
 #define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted
diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
index 858f827a0a..c357e2fbac 100644
--- a/libavcodec/avpacket.c
+++ b/libavcodec/avpacket.c
@@ -46,6 +46,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
     pkt->buf                  = NULL;
     pkt->side_data            = NULL;
     pkt->side_data_elems      = 0;
+    pkt->source_filename      = NULL;
 }
 
 AVPacket *av_packet_alloc(void)
diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c
index f8b4a655a5..02119d89fc 100644
--- a/libavformat/img2dec.c
+++ b/libavformat/img2dec.c
@@ -485,6 +485,15 @@ int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt)
 
     if (s->is_pipe)
         pkt->pos = avio_tell(f[0]);
+    else {
+        // Set the filename which corresponds to this packet.
+        pkt->source_filename = av_malloc(strlen(filename));
+        if (!pkt->source_filename) {
+            av_log(NULL, AV_LOG_FATAL, "Failed to allocate source_filename\n");
+            return AVERROR(ENOMEM);
+        }
+        pkt->source_filename = av_asprintf("%s", filename);
+    }
 
     pkt->size = 0;
     for (i = 0; i < 3; i++) {
-- 
2.17.1



More information about the ffmpeg-devel mailing list