This function can be useful for various other subtitles formats.tags/n1.1
| @@ -71,52 +71,6 @@ static int64_t get_pts(const char **buf, int *duration, | |||||
| return AV_NOPTS_VALUE; | return AV_NOPTS_VALUE; | ||||
| } | } | ||||
| 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; | |||||
| av_bprint_clear(buf); | |||||
| 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++; | |||||
| } | |||||
| } | |||||
| static int srt_read_header(AVFormatContext *s) | static int srt_read_header(AVFormatContext *s) | ||||
| { | { | ||||
| SRTContext *srt = s->priv_data; | SRTContext *srt = s->priv_data; | ||||
| @@ -133,7 +87,7 @@ static int srt_read_header(AVFormatContext *s) | |||||
| av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); | av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); | ||||
| while (!url_feof(s->pb)) { | while (!url_feof(s->pb)) { | ||||
| read_chunk(s->pb, &buf); | |||||
| ff_subtitles_read_chunk(s->pb, &buf); | |||||
| if (buf.len) { | if (buf.len) { | ||||
| int64_t pos = avio_tell(s->pb); | int64_t pos = avio_tell(s->pb); | ||||
| @@ -192,3 +192,49 @@ const char *ff_smil_get_attr_ptr(const char *s, const char *attr) | |||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| static inline int is_eol(char c) | |||||
| { | |||||
| return c == '\r' || c == '\n'; | |||||
| } | |||||
| void ff_subtitles_read_chunk(AVIOContext *pb, AVBPrint *buf) | |||||
| { | |||||
| char eol_buf[5]; | |||||
| int n = 0, i = 0, nb_eol = 0; | |||||
| av_bprint_clear(buf); | |||||
| 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++; | |||||
| } | |||||
| } | |||||
| @@ -81,4 +81,19 @@ int ff_smil_extract_next_chunk(AVIOContext *pb, AVBPrint *buf, char *c); | |||||
| */ | */ | ||||
| const char *ff_smil_get_attr_ptr(const char *s, const char *attr); | const char *ff_smil_get_attr_ptr(const char *s, const char *attr); | ||||
| /** | |||||
| * @brief Read a subtitles chunk. | |||||
| * | |||||
| * A chunk is defined by a multiline "event", ending with a second line break. | |||||
| * The trailing line breaks are trimmed. CLRF are supported. | |||||
| * Example: "foo\r\nbar\r\n\r\nnext" will print "foo\r\nbar" into buf, and pb | |||||
| * will focus on the 'n' of the "next" string. | |||||
| * | |||||
| * @param pb I/O context | |||||
| * @param buf an initialized buf where the chunk is written | |||||
| * | |||||
| * @note buf is cleared before writing into it. | |||||
| */ | |||||
| void ff_subtitles_read_chunk(AVIOContext *pb, AVBPrint *buf); | |||||
| #endif /* AVFORMAT_SUBTITLES_H */ | #endif /* AVFORMAT_SUBTITLES_H */ | ||||