Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * Copyright (c) 2012 Clément Bœsch | ||
3 | * | ||
4 | * This file is part of FFmpeg. | ||
5 | * | ||
6 | * FFmpeg is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU Lesser General Public | ||
8 | * License as published by the Free Software Foundation; either | ||
9 | * version 2.1 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * FFmpeg is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * Lesser General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU Lesser General Public | ||
17 | * License along with FFmpeg; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | */ | ||
20 | |||
21 | #ifndef AVFORMAT_SUBTITLES_H | ||
22 | #define AVFORMAT_SUBTITLES_H | ||
23 | |||
24 | #include <stdint.h> | ||
25 | #include <stddef.h> | ||
26 | #include "avformat.h" | ||
27 | #include "libavutil/bprint.h" | ||
28 | #include "avio_internal.h" | ||
29 | |||
30 | enum sub_sort { | ||
31 | SUB_SORT_TS_POS = 0, ///< sort by timestamps, then position | ||
32 | SUB_SORT_POS_TS, ///< sort by position, then timestamps | ||
33 | }; | ||
34 | |||
35 | enum ff_utf_type { | ||
36 | FF_UTF_8, // or other 8 bit encodings | ||
37 | FF_UTF16LE, | ||
38 | FF_UTF16BE, | ||
39 | }; | ||
40 | |||
41 | typedef struct { | ||
42 | int type; | ||
43 | AVIOContext *pb; | ||
44 | unsigned char buf[8]; | ||
45 | int buf_pos, buf_len; | ||
46 | FFIOContext buf_pb; | ||
47 | } FFTextReader; | ||
48 | |||
49 | /** | ||
50 | * Initialize the FFTextReader from the given AVIOContext. This function will | ||
51 | * read some bytes from pb, and test for UTF-8 or UTF-16 BOMs. Further accesses | ||
52 | * to FFTextReader will read more data from pb. | ||
53 | * If s is not NULL, the user will be warned if a UTF-16 conversion takes place. | ||
54 | * | ||
55 | * The purpose of FFTextReader is to transparently convert read data to UTF-8 | ||
56 | * if the stream had a UTF-16 BOM. | ||
57 | * | ||
58 | * @param s Pointer to provide av_log context | ||
59 | * @param r object which will be initialized | ||
60 | * @param pb stream to read from (referenced as long as FFTextReader is in use) | ||
61 | */ | ||
62 | void ff_text_init_avio(void *s, FFTextReader *r, AVIOContext *pb); | ||
63 | |||
64 | /** | ||
65 | * Similar to ff_text_init_avio(), but sets it up to read from a bounded buffer. | ||
66 | * | ||
67 | * @param r object which will be initialized | ||
68 | * @param buf buffer to read from (referenced as long as FFTextReader is in use) | ||
69 | * @param size size of buf | ||
70 | */ | ||
71 | void ff_text_init_buf(FFTextReader *r, const void *buf, size_t size); | ||
72 | |||
73 | /** | ||
74 | * Return the byte position of the next byte returned by ff_text_r8(). For | ||
75 | * UTF-16 source streams, this will return the original position, but it will | ||
76 | * be incorrect if a codepoint was only partially read with ff_text_r8(). | ||
77 | */ | ||
78 | int64_t ff_text_pos(FFTextReader *r); | ||
79 | |||
80 | /** | ||
81 | * Return the next byte. The return value is always 0 - 255. Returns 0 on EOF. | ||
82 | * If the source stream is UTF-16, this reads from the stream converted to | ||
83 | * UTF-8. On invalid UTF-16, 0 is returned. | ||
84 | */ | ||
85 | int ff_text_r8(FFTextReader *r); | ||
86 | |||
87 | /** | ||
88 | * Return non-zero if EOF was reached. | ||
89 | */ | ||
90 | int ff_text_eof(FFTextReader *r); | ||
91 | |||
92 | /** | ||
93 | * Like ff_text_r8(), but don't remove the byte from the buffer. | ||
94 | */ | ||
95 | int ff_text_peek_r8(FFTextReader *r); | ||
96 | |||
97 | /** | ||
98 | * Read the given number of bytes (in UTF-8). On error or EOF, \0 bytes are | ||
99 | * written. | ||
100 | */ | ||
101 | void ff_text_read(FFTextReader *r, char *buf, size_t size); | ||
102 | |||
103 | typedef struct { | ||
104 | AVPacket **subs; ///< array of subtitles packets | ||
105 | int nb_subs; ///< number of subtitles packets | ||
106 | int allocated_size; ///< allocated size for subs | ||
107 | int current_sub_idx; ///< current position for the read packet callback | ||
108 | enum sub_sort sort; ///< sort method to use when finalizing subtitles | ||
109 | int keep_duplicates; ///< set to 1 to keep duplicated subtitle events | ||
110 | } FFDemuxSubtitlesQueue; | ||
111 | |||
112 | /** | ||
113 | * Insert a new subtitle event. | ||
114 | * | ||
115 | * @param event the subtitle line (not zero terminated) or NULL on not yet available event | ||
116 | * @param len the length of the event (in strlen() sense, so without '\0') | ||
117 | * @param merge set to 1 if the current event should be concatenated with the | ||
118 | * previous one instead of adding a new entry, 0 otherwise | ||
119 | */ | ||
120 | AVPacket *ff_subtitles_queue_insert(FFDemuxSubtitlesQueue *q, | ||
121 | const uint8_t *event, size_t len, int merge); | ||
122 | |||
123 | /** | ||
124 | * Same as ff_subtitles_queue_insert but takes an AVBPrint input. | ||
125 | * Avoids common errors like handling incomplete AVBPrint. | ||
126 | */ | ||
127 | AVPacket *ff_subtitles_queue_insert_bprint(FFDemuxSubtitlesQueue *q, | ||
128 | const AVBPrint *event, int merge); | ||
129 | /** | ||
130 | * Set missing durations, sort subtitles by PTS (and then byte position), and | ||
131 | * drop duplicated events. | ||
132 | */ | ||
133 | void ff_subtitles_queue_finalize(void *log_ctx, FFDemuxSubtitlesQueue *q); | ||
134 | |||
135 | /** | ||
136 | * Generic read_packet() callback for subtitles demuxers using this queue | ||
137 | * system. | ||
138 | */ | ||
139 | int ff_subtitles_queue_read_packet(FFDemuxSubtitlesQueue *q, AVPacket *pkt); | ||
140 | |||
141 | /** | ||
142 | * Update current_sub_idx to emulate a seek. Except the first parameter, it | ||
143 | * matches FFInputFormat->read_seek2 prototypes. | ||
144 | */ | ||
145 | int ff_subtitles_queue_seek(FFDemuxSubtitlesQueue *q, AVFormatContext *s, int stream_index, | ||
146 | int64_t min_ts, int64_t ts, int64_t max_ts, int flags); | ||
147 | |||
148 | /** | ||
149 | * Remove and destroy all the subtitles packets. | ||
150 | */ | ||
151 | void ff_subtitles_queue_clean(FFDemuxSubtitlesQueue *q); | ||
152 | |||
153 | int ff_subtitles_read_packet(AVFormatContext *s, AVPacket *pkt); | ||
154 | |||
155 | int ff_subtitles_read_seek(AVFormatContext *s, int stream_index, | ||
156 | int64_t min_ts, int64_t ts, int64_t max_ts, int flags); | ||
157 | |||
158 | int ff_subtitles_read_close(AVFormatContext *s); | ||
159 | |||
160 | /** | ||
161 | * SMIL helper to load next chunk ("<...>" or untagged content) in buf. | ||
162 | * | ||
163 | * @param c cached character, to avoid a backward seek | ||
164 | * @return size of chunk or error, e.g. AVERROR(ENOMEM) on incomplete buf | ||
165 | */ | ||
166 | int ff_smil_extract_next_text_chunk(FFTextReader *tr, AVBPrint *buf, char *c); | ||
167 | |||
168 | /** | ||
169 | * SMIL helper to point on the value of an attribute in the given tag. | ||
170 | * | ||
171 | * @param s SMIL tag ("<...>") | ||
172 | * @param attr the attribute to look for | ||
173 | */ | ||
174 | const char *ff_smil_get_attr_ptr(const char *s, const char *attr); | ||
175 | |||
176 | /** | ||
177 | * @brief Same as ff_subtitles_read_text_chunk(), but read from an AVIOContext. | ||
178 | */ | ||
179 | av_warn_unused_result | ||
180 | int ff_subtitles_read_chunk(AVIOContext *pb, AVBPrint *buf); | ||
181 | |||
182 | /** | ||
183 | * @brief Read a subtitles chunk from FFTextReader. | ||
184 | * | ||
185 | * A chunk is defined by a multiline "event", ending with a second line break. | ||
186 | * The trailing line breaks are trimmed. CRLF are supported. | ||
187 | * Example: "foo\r\nbar\r\n\r\nnext" will print "foo\r\nbar" into buf, and pb | ||
188 | * will focus on the 'n' of the "next" string. | ||
189 | * | ||
190 | * @param tr I/O context | ||
191 | * @param buf an initialized buf where the chunk is written | ||
192 | * @return 0 on success, error value otherwise, e.g. AVERROR(ENOMEM) if buf is incomplete | ||
193 | * | ||
194 | * @note buf is cleared before writing into it. | ||
195 | */ | ||
196 | av_warn_unused_result | ||
197 | int ff_subtitles_read_text_chunk(FFTextReader *tr, AVBPrint *buf); | ||
198 | |||
199 | /** | ||
200 | * Get the number of characters to increment to jump to the next line, or to | ||
201 | * the end of the string. | ||
202 | * The function handles the following line breaks schemes: | ||
203 | * LF, CRLF (MS), or standalone CR (old MacOS). | ||
204 | */ | ||
205 | 17856 | static av_always_inline int ff_subtitles_next_line(const char *ptr) | |
206 | { | ||
207 | 17856 | int n = strcspn(ptr, "\r\n"); | |
208 | 17856 | ptr += n; | |
209 |
2/2✓ Branch 0 taken 2504 times.
✓ Branch 1 taken 17856 times.
|
20360 | while (*ptr == '\r') { |
210 | 2504 | ptr++; | |
211 | 2504 | n++; | |
212 | } | ||
213 |
2/2✓ Branch 0 taken 3798 times.
✓ Branch 1 taken 14058 times.
|
17856 | if (*ptr == '\n') |
214 | 3798 | n++; | |
215 | 17856 | return n; | |
216 | } | ||
217 | |||
218 | /** | ||
219 | * Read a line of text. Discards line ending characters. | ||
220 | * The function handles the following line breaks schemes: | ||
221 | * LF, CRLF (MS), or standalone CR (old MacOS). | ||
222 | * | ||
223 | * Returns the number of bytes written to buf. Always writes a terminating 0, | ||
224 | * similar as with snprintf. | ||
225 | * | ||
226 | * @note returns a negative error code if a \0 byte is found | ||
227 | */ | ||
228 | ptrdiff_t ff_subtitles_read_line(FFTextReader *tr, char *buf, size_t size); | ||
229 | |||
230 | #endif /* AVFORMAT_SUBTITLES_H */ | ||
231 |