diff --git a/libavformat/srtdec.c b/libavformat/srtdec.c index 9089331849..f55fb11774 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,69 @@ 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++; + } + + /* FIXME: remove the following when the lavc SubRip decoder is fixed + * (trailing tags are not correctly flushed, see what happens to FATE when + * you disable this code) */ + 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-bufferpb, &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 +161,7 @@ static int srt_read_packet(AVFormatContext *s, AVPacket *pkt) } } } + av_bprint_finalize(&buf, NULL); return res; }