1 /*
2 * TED Talks captions format decoder
3 * Copyright (c) 2012 Nicolas George
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
28
34
36 { "start_time", "set the start time (offset) of the subtitles, in ms",
38 { .i64 = 15000 }, INT64_MIN, INT64_MAX,
41 };
42
48 };
49
50 #define BETWEEN(a, amin, amax) ((unsigned)((a) - (amin)) <= (amax) - (amin))
51
52 #define HEX_DIGIT_TEST(c) (BETWEEN(c, '0', '9') || BETWEEN((c) | 32, 'a', 'z'))
53 #define HEX_DIGIT_VAL(c) ((c) <= '9' ? (c) - '0' : ((c) | 32) - 'a' + 10)
54 #define ERR_CODE(c) (c < 0 ? c : AVERROR_INVALIDDATA)
55
57 {
58 int bytes, i;
59
60 if (c <= 0x7F) {
62 return;
63 }
65 av_bprint_chars(bp, (c >> (bytes * 6)) | ((0xFF80 >> bytes) & 0xFF), 1);
66 for (i = bytes - 1; i >= 0; i--)
68 }
69
71 {
74 *cur_byte = ret > 0 ? b : ret == 0 ?
AVERROR_EOF : ret;
75 }
76
78 {
79 while (*cur_byte == ' ' || *cur_byte == '\t' ||
80 *cur_byte == '\n' || *cur_byte == '\r')
82 }
83
85 {
87 if (*cur_byte != c)
90 return 0;
91 }
92
94 {
95 int ret;
96
99 if (ret < 0)
100 goto fail;
101 while (*cur_byte > 0 && *cur_byte != '"') {
102 if (*cur_byte == '\\') {
104 if (*cur_byte < 0) {
106 goto fail;
107 }
108 if ((*cur_byte | 32) == 'u') {
109 unsigned chr = 0, i;
110 for (i = 0; i < 4; i++) {
114 goto fail;
115 }
117 }
119 } else {
121 }
122 } else {
124 }
126 }
128 if (ret < 0)
129 goto fail;
132 goto fail;
133 }
134 return 0;
135
136 fail:
138 return ret;
139 }
140
142 {
143 int ret;
144
146 if (ret < 0)
147 return ret;
149 if (ret < 0)
150 return ret;
151 return 0;
152 }
153
155 {
156 const char *text[] = { "false", "true" }, *p;
157 int i;
158
160 for (i = 0; i < 2; i++) {
161 p = text[i];
162 if (*cur_byte != *p)
163 continue;
165 if (*cur_byte != *p)
167 if (
BETWEEN(*cur_byte | 32,
'a',
'z'))
169 *result = i;
170 return 0;
171 }
173 }
174
176 {
177 int64_t val = 0;
178
180 if ((unsigned)*cur_byte - '0' > 9)
182 while (
BETWEEN(*cur_byte,
'0',
'9')) {
183 val = val * 10 + (*cur_byte - '0');
185 }
186 *result = val;
187 return 0;
188 }
189
191 {
192 int ret, cur_byte, start_of_par;
196
199 if (ret < 0)
202 if (ret < 0 || strcmp(label.str, "captions"))
205 if (ret < 0)
207 while (1) {
208 content.size = 0;
211 if (ret < 0)
212 return ret;
214 while (1) {
216 if (ret < 0)
217 return ret;
218 if (!strcmp(label.str, "startOfParagraph")) {
220 if (ret < 0)
221 return ret;
222 } else if (!strcmp(label.str, "content")) {
224 if (ret < 0)
225 return ret;
226 } else if (!strcmp(label.str, "startTime")) {
228 if (ret < 0)
229 return ret;
230 } else if (!strcmp(label.str, "duration")) {
231 ret =
parse_int(pb, &cur_byte, &duration);
232 if (ret < 0)
233 return ret;
234 } else {
236 }
238 if (cur_byte != ',')
239 break;
241 }
243 if (ret < 0)
244 return ret;
245
250 if (!pkt)
256
258 if (cur_byte != ',')
259 break;
261 }
263 if (ret < 0)
264 return ret;
266 if (ret < 0)
267 return ret;
271 return 0;
272 }
273
275 {
278 int ret, i;
280
282 if (ret < 0) {
287 return ret;
288 }
292
295 if (!st)
304
305 return 0;
306 }
307
309 {
311
313 }
314
316 {
318
320 return 0;
321 }
322
324 {
325 static const char *const tags[] = {
326 "\"captions\"", "\"duration\"", "\"content\"",
327 "\"startOfParagraph\"", "\"startTime\"",
328 };
329 unsigned i, count = 0;
331
332 if (p->
buf[strspn(p->
buf,
" \t\r\n")] !=
'{')
333 return 0;
335 if (!(t = strstr(p->
buf, tags[i])))
336 continue;
337 t += strlen(tags[i]);
338 t += strspn(t, " \t\r\n");
339 if (*t == ':')
340 count++;
341 }
344 }
345
347 int64_t min_ts, int64_t ts, int64_t max_ts,
349 {
352 min_ts, ts, max_ts, flags);
353 }
354
356 .
name =
"tedcaptions",
359 .priv_class = &tedcaptions_demuxer_class,
365 };