lavf/webvttdec: save cue id and settings as side data
authorMatthew Heaney <matthewjheaney@google.com>
Fri, 31 May 2013 23:27:32 +0000 (16:27 -0700)
committerClément Bœsch <ubitux@gmail.com>
Sat, 1 Jun 2013 13:12:49 +0000 (15:12 +0200)
Currently the WebVTT demuxer parses the cues but throws away
the cue id (the optional first line of the cue) and cue
settings (the optional rendering instructions that follow
the timestamp).

However, in order to write inband text tracks (to WebM
files), the entire cue payload from the WebVTT source must
be preserved.

This commit makes no change to the data part of the output
buffer packet (where the actual cue text is stored), but
does add the cue id and settings as a side data items, if
they're present in the cue. Existing code that cares only
about the data part of the packet can continue to ignore the
side data.

There are two new packet data type flags,
AV_PKT_DATA_WEBVTT_IDENTIFIER and
AV_PKT_DATA_WEBVTT_SETTINGS.

libavcodec/avcodec.h
libavcodec/version.h
libavformat/webvttdec.c

index 93d63e8..5ece48c 100644 (file)
@@ -1008,6 +1008,17 @@ enum AVPacketSideDataType {
      * by data.
      */
     AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL,
+
+    /**
+     * The optional first identifier line of a WebVTT cue.
+     */
+    AV_PKT_DATA_WEBVTT_IDENTIFIER,
+
+    /**
+     * The optional settings (rendering instructions) that immediately
+     * follow the timestamp specifier of a WebVTT cue.
+     */
+    AV_PKT_DATA_WEBVTT_SETTINGS,
 };
 
 /**
index b904048..4c2c21b 100644 (file)
@@ -29,8 +29,8 @@
 #include "libavutil/avutil.h"
 
 #define LIBAVCODEC_VERSION_MAJOR 55
-#define LIBAVCODEC_VERSION_MINOR  12
-#define LIBAVCODEC_VERSION_MICRO 102
+#define LIBAVCODEC_VERSION_MINOR  13
+#define LIBAVCODEC_VERSION_MICRO 100
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                LIBAVCODEC_VERSION_MINOR, \
index 694a020..894a762 100644 (file)
@@ -74,8 +74,8 @@ static int webvtt_read_header(AVFormatContext *s)
         int i;
         int64_t pos;
         AVPacket *sub;
-        const char *p, *identifier;
-        //const char *settings = NULL;
+        const char *p, *identifier, *settings;
+        int identifier_len, settings_len;
         int64_t ts_start, ts_end;
 
         ff_subtitles_read_chunk(s->pb, &cue);
@@ -92,15 +92,23 @@ static int webvtt_read_header(AVFormatContext *s)
             continue;
 
         /* optional cue identifier (can be a number like in SRT or some kind of
-         * chaptering id), silently skip it */
-        for (i = 0; p[i] && p[i] != '\n'; i++) {
+         * chaptering id) */
+        for (i = 0; p[i] && p[i] != '\n' && p[i] != '\r'; i++) {
             if (!strncmp(p + i, "-->", 3)) {
                 identifier = NULL;
                 break;
             }
         }
-        if (identifier)
-            p += strcspn(p, "\n");
+        if (!identifier)
+            identifier_len = 0;
+        else {
+            identifier_len = strcspn(p, "\r\n");
+            p += identifier_len;
+            if (*p == '\r')
+                p++;
+            if (*p == '\n')
+                p++;
+        }
 
         /* cue timestamps */
         if ((ts_start = read_ts(p)) == AV_NOPTS_VALUE)
@@ -112,14 +120,15 @@ static int webvtt_read_header(AVFormatContext *s)
         if ((ts_end = read_ts(p)) == AV_NOPTS_VALUE)
             break;
 
-        /* optional cue settings, TODO: store in side_data */
+        /* optional cue settings */
         p += strcspn(p, "\n\t ");
         while (*p == '\t' || *p == ' ')
             p++;
-        if (*p != '\n') {
-            //settings = p;
-            p += strcspn(p, "\n");
-        }
+        settings = p;
+        settings_len = strcspn(p, "\r\n");
+        p += settings_len;
+        if (*p == '\r')
+            p++;
         if (*p == '\n')
             p++;
 
@@ -132,6 +141,28 @@ static int webvtt_read_header(AVFormatContext *s)
         sub->pos = pos;
         sub->pts = ts_start;
         sub->duration = ts_end - ts_start;
+
+        if (identifier_len) {
+            uint8_t *buf = av_packet_new_side_data(sub,
+                                                   AV_PKT_DATA_WEBVTT_IDENTIFIER,
+                                                   identifier_len);
+            if (!buf) {
+                res = AVERROR(ENOMEM);
+                goto end;
+            }
+            memcpy(buf, identifier, identifier_len);
+        }
+
+        if (settings_len) {
+            uint8_t *buf = av_packet_new_side_data(sub,
+                                                   AV_PKT_DATA_WEBVTT_SETTINGS,
+                                                   settings_len);
+            if (!buf) {
+                res = AVERROR(ENOMEM);
+                goto end;
+            }
+            memcpy(buf, settings, settings_len);
+        }
     }
 
     ff_subtitles_queue_finalize(&webvtt->q);