Browse code

lavf/srtdec: trim line break event separators from packet.

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 because
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.

Clément Bœsch authored on 2012/11/11 08:06:58
Showing 1 changed files
... ...
@@ -21,6 +21,7 @@
21 21
 
22 22
 #include "avformat.h"
23 23
 #include "internal.h"
24
+#include "libavutil/bprint.h"
24 25
 #include "libavutil/intreadwrite.h"
25 26
 
26 27
 static int srt_probe(AVProbeData *p)
... ...
@@ -52,7 +53,7 @@ static int srt_read_header(AVFormatContext *s)
52 52
     return 0;
53 53
 }
54 54
 
55
-static int64_t get_pts(char **buf, int *duration,
55
+static int64_t get_pts(const char **buf, int *duration,
56 56
                        int32_t *x1, int32_t *y1, int32_t *x2, int32_t *y2)
57 57
 {
58 58
     int i;
... ...
@@ -81,27 +82,69 @@ static inline int is_eol(char c)
81 81
     return c == '\r' || c == '\n';
82 82
 }
83 83
 
84
+static void read_chunk(AVIOContext *pb, AVBPrint *buf)
85
+{
86
+    char eol_buf[5];
87
+    int n = 0, i = 0, nb_eol = 0;
88
+
89
+    for (;;) {
90
+        char c = avio_r8(pb);
91
+
92
+        if (!c)
93
+            break;
94
+
95
+        /* ignore all initial line breaks */
96
+        if (n == 0 && is_eol(c))
97
+            continue;
98
+
99
+        /* line break buffering: we don't want to add the trailing \r\n */
100
+        if (is_eol(c)) {
101
+            nb_eol += c == '\n';
102
+            if (nb_eol == 2)
103
+                break;
104
+            eol_buf[i++] = c;
105
+            if (i == sizeof(eol_buf) - 1)
106
+                break;
107
+            continue;
108
+        }
109
+
110
+        /* only one line break followed by data: we flush the line breaks
111
+         * buffer */
112
+        if (i) {
113
+            eol_buf[i] = 0;
114
+            av_bprintf(buf, "%s", eol_buf);
115
+            i = nb_eol = 0;
116
+        }
117
+
118
+        av_bprint_chars(buf, c, 1);
119
+        n++;
120
+    }
121
+
122
+    /* FIXME: remove the following when the lavc SubRip decoder is fixed
123
+     * (trailing tags are not correctly flushed, see what happens to FATE when
124
+     * you disable this code) */
125
+    if (buf->len)
126
+        av_bprintf(buf, "\n");
127
+}
128
+
84 129
 static int srt_read_packet(AVFormatContext *s, AVPacket *pkt)
85 130
 {
86
-    char buffer[2048], *ptr = buffer, *ptr2;
131
+    AVBPrint buf;
87 132
     int64_t pos = avio_tell(s->pb);
88 133
     int res = AVERROR_EOF;
89 134
 
90
-    do {
91
-        ptr2 = ptr;
92
-        ptr += ff_get_line(s->pb, ptr, sizeof(buffer)+buffer-ptr);
93
-    } while (!is_eol(*ptr2) && !url_feof(s->pb) && ptr-buffer<sizeof(buffer)-1);
135
+    av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
136
+    read_chunk(s->pb, &buf);
94 137
 
95
-    if (buffer[0]) {
138
+    if (buf.len) {
96 139
         int64_t pts;
97
-        int duration;
98
-        const char *end = ptr;
140
+        int duration, pkt_size;
141
+        const char *ptr = buf.str;
99 142
         int32_t x1 = -1, y1 = -1, x2 = -1, y2 = -1;
100 143
 
101
-        ptr = buffer;
102 144
         pts = get_pts(&ptr, &duration, &x1, &y1, &x2, &y2);
103
-        if (pts != AV_NOPTS_VALUE &&
104
-            !(res = av_new_packet(pkt, end - ptr))) {
145
+        pkt_size = buf.len - (ptr - buf.str);
146
+        if (pts != AV_NOPTS_VALUE && !(res = av_new_packet(pkt, pkt_size))) {
105 147
             memcpy(pkt->data, ptr, pkt->size);
106 148
             pkt->flags |= AV_PKT_FLAG_KEY;
107 149
             pkt->pos = pos;
... ...
@@ -118,6 +161,7 @@ static int srt_read_packet(AVFormatContext *s, AVPacket *pkt)
118 118
             }
119 119
         }
120 120
     }
121
+    av_bprint_finalize(&buf, NULL);
121 122
     return res;
122 123
 }
123 124