[FFmpeg-devel] [PATCH 2/3] lavf/srtdec: do not put line break event separator into packet.

Clément Bœsch ubitux at gmail.com
Sun Nov 11 00:44:17 CET 2012


The muxer add them automatically, so this avoid having a bunch of line
breaks all over the output files. One '\n' is still kept/added for two
reasons:
 - that line break can be considered part of the subtitle event, while
   the second one (which is now trimmed) is an event separator.
 - the lavc subrip decoder seems to have trouble with line ending
   abruptly (it doesn't flush correctly the tags). This bug is harmless
   but should be fixed; though, this doesn't look like a trivial change.
   When this bug gets fixed, we can consider removing the '\n' at the
   end of the packet.

The 2048B buffer limit was also removed while moving to AVBPrint API.
Note that this doesn't really matter since the decoder is limited as
well.
---
 libavformat/srtdec.c | 65 ++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 53 insertions(+), 12 deletions(-)

diff --git a/libavformat/srtdec.c b/libavformat/srtdec.c
index 9089331..457e101 100644
--- a/libavformat/srtdec.c
+++ b/libavformat/srtdec.c
@@ -21,6 +21,7 @@
 
 #include "avformat.h"
 #include "internal.h"
+#include "libavutil/bprint.h"
 #include "libavutil/intreadwrite.h"
 
 static int srt_probe(AVProbeData *p)
@@ -52,7 +53,7 @@ static int srt_read_header(AVFormatContext *s)
     return 0;
 }
 
-static int64_t get_pts(char **buf, int *duration,
+static int64_t get_pts(const char **buf, int *duration,
                        int32_t *x1, int32_t *y1, int32_t *x2, int32_t *y2)
 {
     int i;
@@ -81,27 +82,66 @@ static inline int is_eol(char c)
     return c == '\r' || c == '\n';
 }
 
+static void read_chunk(AVIOContext *pb, AVBPrint *buf)
+{
+    char eol_buf[5];
+    int n = 0, i = 0, nb_eol = 0;
+
+    for (;;) {
+        char c = avio_r8(pb);
+
+        if (!c)
+            break;
+
+        /* ignore all initial line breaks */
+        if (n == 0 && is_eol(c))
+            continue;
+
+        /* line break buffering: we don't want to add the trailing \r\n */
+        if (is_eol(c)) {
+            nb_eol += c == '\n';
+            if (nb_eol == 2)
+                break;
+            eol_buf[i++] = c;
+            if (i == sizeof(eol_buf) - 1)
+                break;
+            continue;
+        }
+
+        /* only one line break followed by data: we flush the line breaks
+         * buffer */
+        if (i) {
+            eol_buf[i] = 0;
+            av_bprintf(buf, "%s", eol_buf);
+            i = nb_eol = 0;
+        }
+
+        av_bprint_chars(buf, c, 1);
+        n++;
+    }
+
+    if (buf->len)
+        av_bprintf(buf, "\n");
+}
+
 static int srt_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    char buffer[2048], *ptr = buffer, *ptr2;
+    AVBPrint buf;
     int64_t pos = avio_tell(s->pb);
     int res = AVERROR_EOF;
 
-    do {
-        ptr2 = ptr;
-        ptr += ff_get_line(s->pb, ptr, sizeof(buffer)+buffer-ptr);
-    } while (!is_eol(*ptr2) && !url_feof(s->pb) && ptr-buffer<sizeof(buffer)-1);
+    av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
+    read_chunk(s->pb, &buf);
 
-    if (buffer[0]) {
+    if (buf.len) {
         int64_t pts;
-        int duration;
-        const char *end = ptr;
+        int duration, pkt_size;
+        const char *ptr = buf.str;
         int32_t x1 = -1, y1 = -1, x2 = -1, y2 = -1;
 
-        ptr = buffer;
         pts = get_pts(&ptr, &duration, &x1, &y1, &x2, &y2);
-        if (pts != AV_NOPTS_VALUE &&
-            !(res = av_new_packet(pkt, end - ptr))) {
+        pkt_size = buf.len - (ptr - buf.str);
+        if (pts != AV_NOPTS_VALUE && !(res = av_new_packet(pkt, pkt_size))) {
             memcpy(pkt->data, ptr, pkt->size);
             pkt->flags |= AV_PKT_FLAG_KEY;
             pkt->pos = pos;
@@ -118,6 +158,7 @@ static int srt_read_packet(AVFormatContext *s, AVPacket *pkt)
             }
         }
     }
+    av_bprint_finalize(&buf, NULL);
     return res;
 }
 
-- 
1.8.0



More information about the ffmpeg-devel mailing list