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 /**
22 * @file
23 * WebVTT subtitle demuxer
24 * @see http://dev.w3.org/html5/webvtt/
25 */
26
34
35 typedef struct {
40
42 {
43 const uint8_t *ptr = p->
buf;
44
46 ptr += 3; /* skip UTF-8 BOM */
47 if (!strncmp(ptr, "WEBVTT", 6) &&
48 (!ptr[6] || strchr("\n\r\t ", ptr[6])))
50 return 0;
51 }
52
54 {
56 if (sscanf(
s,
"%u:%u:%u.%u", &hh, &mm, &
ss, &ms) == 4)
return (hh*3600LL + mm*60LL +
ss) * 1000LL + ms;
57 if (sscanf(
s,
"%u:%u.%u", &mm, &
ss, &ms) == 3)
return ( mm*60LL +
ss) * 1000LL + ms;
59 }
60
62 {
64 AVBPrint cue;
65 int res = 0;
67
68 if (!st)
74
76
77 for (;;) {
81 const char *p, *identifier, *settings;
82 size_t identifier_len, settings_len;
84
86 if (res < 0)
87 goto end;
88
89 if (!cue.len)
90 break;
91
92 p = identifier = cue.str;
94
95 /* ignore header chunk */
96 if (!strncmp(p, "\xEF\xBB\xBFWEBVTT", 9) ||
97 !strncmp(p, "WEBVTT", 6) ||
98 !strncmp(p, "STYLE", 5) ||
99 !strncmp(p, "REGION", 6) ||
100 !strncmp(p, "NOTE", 4))
101 continue;
102
103 /* optional cue identifier (can be a number like in SRT or some kind of
104 * chaptering id) */
105 for (
i = 0; p[
i] && p[
i] !=
'\n' && p[
i] !=
'\r';
i++) {
106 if (!strncmp(p +
i,
"-->", 3)) {
108 break;
109 }
110 }
111 if (!identifier)
112 identifier_len = 0;
113 else {
114 identifier_len = strcspn(p, "\r\n");
115 p += identifier_len;
116 if (*p == '\r')
117 p++;
118 if (*p == '\n')
119 p++;
120 }
121
122 /* cue timestamps */
124 break;
125 if (!(p = strstr(p, "-->")))
126 break;
127 p += 2;
128 do p++; while (*p == ' ' || *p == '\t');
130 break;
131
132 /* optional cue settings */
133 p += strcspn(p, "\n\r\t ");
134 while (*p == '\t' || *p == ' ')
135 p++;
136 settings = p;
137 settings_len = strcspn(p, "\r\n");
138 p += settings_len;
139 if (*p == '\r')
140 p++;
141 if (*p == '\n')
142 p++;
143
144 /* create packet */
146 if (!sub) {
148 goto end;
149 }
153
154 #define SET_SIDE_DATA(name, type) do { \
155 if (name##_len) { \
156 uint8_t *buf = av_packet_new_side_data(sub, type, name##_len); \
157 if (!buf) { \
158 res = AVERROR(ENOMEM); \
159 goto end; \
160 } \
161 memcpy(buf, name, name##_len); \
162 } \
163 } while (0)
164
167 }
168
170
171 end:
173 return res;
174 }
175
177 {
180 }
181
184 {
187 min_ts, ts, max_ts,
flags);
188 }
189
191 {
194 return 0;
195 }
196
197 #define OFFSET(x) offsetof(WebVTTContext, x)
198 #define KIND_FLAGS AV_OPT_FLAG_SUBTITLE_PARAM|AV_OPT_FLAG_DECODING_PARAM
199
207 };
208
214 };
215
219 .p.extensions = "vtt",
228 };