[FFmpeg-devel] [PATCH 2/4] lavf/webvtt: preserve comments

rcombs rcombs at rcombs.me
Thu May 28 08:13:16 EEST 2020


---
 libavcodec/avpacket.c   |  1 +
 libavcodec/packet.h     |  6 ++++++
 libavformat/webvttdec.c | 25 ++++++++++++++++++++++---
 libavformat/webvttenc.c | 10 ++++++++--
 4 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
index 033f2d8f26..d62d93346c 100644
--- a/libavcodec/avpacket.c
+++ b/libavcodec/avpacket.c
@@ -399,6 +399,7 @@ const char *av_packet_side_data_name(enum AVPacketSideDataType type)
     case AV_PKT_DATA_PRFT:                       return "Producer Reference Time";
     case AV_PKT_DATA_ICC_PROFILE:                return "ICC Profile";
     case AV_PKT_DATA_DOVI_CONF:                  return "DOVI configuration record";
+    case AV_PKT_DATA_WEBVTT_COMMENT:             return "WebVTT Comment";
     }
     return NULL;
 }
diff --git a/libavcodec/packet.h b/libavcodec/packet.h
index 41485f4527..6b282f04c9 100644
--- a/libavcodec/packet.h
+++ b/libavcodec/packet.h
@@ -282,6 +282,12 @@ enum AVPacketSideDataType {
      */
     AV_PKT_DATA_DOVI_CONF,
 
+    /**
+     * The optional comment data that comes before the identifier or timing block
+     * of a WebVTT cue. Must end with a line break.
+     */
+    AV_PKT_DATA_WEBVTT_COMMENT,
+
     /**
      * The number of side data types.
      * This is not part of the public API/ABI in the sense that it may
diff --git a/libavformat/webvttdec.c b/libavformat/webvttdec.c
index 6c4d5f6736..bc4ef45fb6 100644
--- a/libavformat/webvttdec.c
+++ b/libavformat/webvttdec.c
@@ -60,7 +60,7 @@ static int64_t read_ts(const char *s)
 static int webvtt_read_header(AVFormatContext *s)
 {
     WebVTTContext *webvtt = s->priv_data;
-    AVBPrint cue;
+    AVBPrint cue, com;
     int res = 0;
     AVStream *st = avformat_new_stream(s, NULL);
 
@@ -72,6 +72,7 @@ static int webvtt_read_header(AVFormatContext *s)
     st->disposition |= webvtt->kind;
 
     av_bprint_init(&cue,    0, AV_BPRINT_SIZE_UNLIMITED);
+    av_bprint_init(&com,    0, AV_BPRINT_SIZE_UNLIMITED);
 
     for (;;) {
         int i;
@@ -91,10 +92,15 @@ static int webvtt_read_header(AVFormatContext *s)
 
         /* ignore header chunk */
         if (!strncmp(p, "\xEF\xBB\xBFWEBVTT", 9) ||
-            !strncmp(p, "WEBVTT", 6) ||
-            !strncmp(p, "NOTE", 4))
+            !strncmp(p, "WEBVTT", 6))
             continue;
 
+        if (!strncmp(p, "NOTE", 4) &&
+            (p[4] == ' ' || p[4] == '\t' || p[4] == '\n' || p[4] == '\r')) {
+            av_bprintf(&com, "%s%s\n", com.len ? "\n" : "", p);
+            continue;
+        }
+
         /* optional cue identifier (can be a number like in SRT or some kind of
          * chaptering id) */
         for (i = 0; p[i] && p[i] != '\n' && p[i] != '\r'; i++) {
@@ -159,12 +165,25 @@ static int webvtt_read_header(AVFormatContext *s)
 
         SET_SIDE_DATA(identifier, AV_PKT_DATA_WEBVTT_IDENTIFIER);
         SET_SIDE_DATA(settings,   AV_PKT_DATA_WEBVTT_SETTINGS);
+        if (com.len) {
+            char *com_str;
+            if ((res = av_bprint_finalize(&com, &com_str)) < 0)
+                goto end;
+
+            if ((res = av_packet_add_side_data(sub, AV_PKT_DATA_WEBVTT_COMMENT, com_str, com.len)) < 0) {
+                av_free(com_str);
+                goto end;
+            }
+
+            av_bprint_init(&com,    0, AV_BPRINT_SIZE_UNLIMITED);
+        }
     }
 
     ff_subtitles_queue_finalize(s, &webvtt->q);
 
 end:
     av_bprint_finalize(&cue,    NULL);
+    av_bprint_finalize(&com,    NULL);
     return res;
 }
 
diff --git a/libavformat/webvttenc.c b/libavformat/webvttenc.c
index cbd989dcb6..ecd508db65 100644
--- a/libavformat/webvttenc.c
+++ b/libavformat/webvttenc.c
@@ -64,11 +64,17 @@ static int webvtt_write_header(AVFormatContext *ctx)
 static int webvtt_write_packet(AVFormatContext *ctx, AVPacket *pkt)
 {
     AVIOContext  *pb = ctx->pb;
-    int id_size, settings_size;
-    uint8_t *id, *settings;
+    int id_size, settings_size, comment_size;
+    uint8_t *id, *settings, *comment;
 
     avio_printf(pb, "\n");
 
+    comment = av_packet_get_side_data(pkt, AV_PKT_DATA_WEBVTT_COMMENT,
+                                      &comment_size);
+
+    if (comment && comment_size > 0)
+        avio_printf(pb, "%.*s\n", comment_size, comment);
+
     id = av_packet_get_side_data(pkt, AV_PKT_DATA_WEBVTT_IDENTIFIER,
                                  &id_size);
 
-- 
2.26.2



More information about the ffmpeg-devel mailing list