]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/subtitles.c
libavformat/dv: Make unchanged function arguments const
[ffmpeg] / libavformat / subtitles.c
index fce2bf190bfbd09d83b400b728bffe6bf1a669a0..95faca6e489e2e9f48cd20ff6ce848f9dd5367d5 100644 (file)
 
 #include "avformat.h"
 #include "subtitles.h"
+#include "avio_internal.h"
 #include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
 
+void ff_text_init_avio(FFTextReader *r, AVIOContext *pb)
+{
+    int i;
+    r->pb = pb;
+    r->buf_pos = r->buf_len = 0;
+    r->type = FF_UTF_8;
+    for (i = 0; i < 2; i++)
+        r->buf[r->buf_len++] = avio_r8(r->pb);
+    if (strncmp("\xFF\xFE", r->buf, 2) == 0) {
+        r->type = FF_UTF16LE;
+        r->buf_pos += 2;
+    } else if (strncmp("\xFE\xFF", r->buf, 2) == 0) {
+        r->type = FF_UTF16BE;
+        r->buf_pos += 2;
+    } else {
+        r->buf[r->buf_len++] = avio_r8(r->pb);
+        if (strncmp("\xEF\xBB\xBF", r->buf, 3) == 0) {
+            // UTF8
+            r->buf_pos += 3;
+        }
+    }
+}
+
+void ff_text_init_buf(FFTextReader *r, void *buf, size_t size)
+{
+    memset(&r->buf_pb, 0, sizeof(r->buf_pb));
+    ffio_init_context(&r->buf_pb, buf, size, 0, NULL, NULL, NULL, NULL);
+    ff_text_init_avio(r, &r->buf_pb);
+}
+
+int64_t ff_text_pos(FFTextReader *r)
+{
+    return avio_tell(r->pb) - r->buf_len + r->buf_pos;
+}
+
+int ff_text_r8(FFTextReader *r)
+{
+    uint32_t val;
+    uint8_t tmp;
+    if (r->buf_pos < r->buf_len)
+        return r->buf[r->buf_pos++];
+    if (r->type == FF_UTF16LE) {
+        GET_UTF16(val, avio_rl16(r->pb), return 0;)
+    } else if (r->type == FF_UTF16BE) {
+        GET_UTF16(val, avio_rb16(r->pb), return 0;)
+    } else {
+        return avio_r8(r->pb);
+    }
+    if (!val)
+        return 0;
+    r->buf_pos = 0;
+    r->buf_len = 0;
+    PUT_UTF8(val, tmp, r->buf[r->buf_len++] = tmp;)
+    return r->buf[r->buf_pos++]; // buf_len is at least 1
+}
+
+void ff_text_read(FFTextReader *r, char *buf, size_t size)
+{
+    for ( ; size > 0; size--)
+        *buf++ = ff_text_r8(r);
+}
+
+int ff_text_eof(FFTextReader *r)
+{
+    return r->buf_pos >= r->buf_len && avio_feof(r->pb);
+}
+
+int ff_text_peek_r8(FFTextReader *r)
+{
+    int c;
+    if (r->buf_pos < r->buf_len)
+        return r->buf[r->buf_pos];
+    c = ff_text_r8(r);
+    if (!avio_feof(r->pb)) {
+        r->buf_pos = 0;
+        r->buf_len = 1;
+        r->buf[0] = c;
+    }
+    return c;
+}
+
 AVPacket *ff_subtitles_queue_insert(FFDemuxSubtitlesQueue *q,
                                     const uint8_t *event, int len, int merge)
 {
@@ -192,20 +274,20 @@ void ff_subtitles_queue_clean(FFDemuxSubtitlesQueue *q)
     q->nb_subs = q->allocated_size = q->current_sub_idx = 0;
 }
 
-int ff_smil_extract_next_chunk(AVIOContext *pb, AVBPrint *buf, char *c)
+int ff_smil_extract_next_text_chunk(FFTextReader *tr, AVBPrint *buf, char *c)
 {
     int i = 0;
     char end_chr;
 
     if (!*c) // cached char?
-        *c = avio_r8(pb);
+        *c = ff_text_r8(tr);
     if (!*c)
         return 0;
 
     end_chr = *c == '<' ? '>' : '<';
     do {
         av_bprint_chars(buf, *c, 1);
-        *c = avio_r8(pb);
+        *c = ff_text_r8(tr);
         i++;
     } while (*c != end_chr && *c);
     if (end_chr == '>') {
@@ -240,7 +322,7 @@ static inline int is_eol(char c)
     return c == '\r' || c == '\n';
 }
 
-void ff_subtitles_read_chunk(AVIOContext *pb, AVBPrint *buf)
+void ff_subtitles_read_text_chunk(FFTextReader *tr, AVBPrint *buf)
 {
     char eol_buf[5], last_was_cr = 0;
     int n = 0, i = 0, nb_eol = 0;
@@ -248,7 +330,7 @@ void ff_subtitles_read_chunk(AVIOContext *pb, AVBPrint *buf)
     av_bprint_clear(buf);
 
     for (;;) {
-        char c = avio_r8(pb);
+        char c = ff_text_r8(tr);
 
         if (!c)
             break;
@@ -281,3 +363,33 @@ void ff_subtitles_read_chunk(AVIOContext *pb, AVBPrint *buf)
         n++;
     }
 }
+
+void ff_subtitles_read_chunk(AVIOContext *pb, AVBPrint *buf)
+{
+    FFTextReader tr;
+    tr.buf_pos = tr.buf_len = 0;
+    tr.type = 0;
+    tr.pb = pb;
+    ff_subtitles_read_text_chunk(&tr, buf);
+}
+
+ptrdiff_t ff_subtitles_read_line(FFTextReader *tr, char *buf, size_t size)
+{
+    size_t cur = 0;
+    if (!size)
+        return 0;
+    while (cur + 1 < size) {
+        unsigned char c = ff_text_r8(tr);
+        if (!c)
+            return ff_text_eof(tr) ? cur : AVERROR_INVALIDDATA;
+        if (c == '\r' || c == '\n')
+            break;
+        buf[cur++] = c;
+        buf[cur] = '\0';
+    }
+    if (ff_text_peek_r8(tr) == '\r')
+        ff_text_r8(tr);
+    if (ff_text_peek_r8(tr) == '\n')
+        ff_text_r8(tr);
+    return cur;
+}