#include "avformat.h"
#include "internal.h"
+#include "libavutil/bprint.h"
#include "libavutil/intreadwrite.h"
static int srt_probe(AVProbeData *p)
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;
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-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;
}
}
}
+ av_bprint_finalize(&buf, NULL);
return res;
}