FFmpeg
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavformat
webvttdec.c
Go to the documentation of this file.
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
27
#include "
avformat.h
"
28
#include "
internal.h
"
29
#include "
subtitles.h
"
30
#include "
libavutil/bprint.h
"
31
#include "
libavutil/intreadwrite.h
"
32
33
typedef
struct
{
34
FFDemuxSubtitlesQueue
q
;
35
}
WebVTTContext
;
36
37
static
int
webvtt_probe
(
AVProbeData
*p)
38
{
39
const
uint8_t
*ptr = p->
buf
;
40
41
if
(
AV_RB24
(ptr) == 0xEFBBBF)
42
ptr += 3;
/* skip UTF-8 BOM */
43
if
(!strncmp(ptr,
"WEBVTT"
, 6) &&
44
(!ptr[6] || strchr(
"\n\r\t "
, ptr[6])))
45
return
AVPROBE_SCORE_MAX
;
46
return
0;
47
}
48
49
static
int64_t
read_ts
(
const
char
*s)
50
{
51
int
hh, mm, ss, ms;
52
if
(sscanf(s,
"%u:%u:%u.%u"
, &hh, &mm, &ss, &ms) == 4)
return
(hh*3600LL + mm*60LL + ss) * 1000LL + ms;
53
if
(sscanf(s,
"%u:%u.%u"
, &mm, &ss, &ms) == 3)
return
( mm*60LL + ss) * 1000LL + ms;
54
return
AV_NOPTS_VALUE
;
55
}
56
57
static
int
webvtt_read_header
(
AVFormatContext
*s)
58
{
59
WebVTTContext
*webvtt = s->
priv_data
;
60
AVBPrint
header, cue;
61
int
res = 0;
62
AVStream
*st =
avformat_new_stream
(s,
NULL
);
63
64
if
(!st)
65
return
AVERROR
(ENOMEM);
66
avpriv_set_pts_info
(st, 64, 1, 1000);
67
st->
codec
->
codec_type
=
AVMEDIA_TYPE_SUBTITLE
;
68
st->
codec
->
codec_id
=
AV_CODEC_ID_WEBVTT
;
69
70
av_bprint_init
(&header, 0,
AV_BPRINT_SIZE_UNLIMITED
);
71
av_bprint_init
(&cue, 0,
AV_BPRINT_SIZE_UNLIMITED
);
72
73
for
(;;) {
74
int
i;
75
int64_t pos;
76
AVPacket
*sub;
77
const
char
*p, *identifier;
78
//const char *settings = NULL;
79
int64_t ts_start, ts_end;
80
81
ff_subtitles_read_chunk
(s->
pb
, &cue);
82
83
if
(!cue.len)
84
break
;
85
86
p = identifier = cue.str;
87
pos =
avio_tell
(s->
pb
);
88
89
/* ignore header chunk */
90
if
(!strncmp(p,
"\xEF\xBB\xBFWEBVTT"
, 9) ||
91
!strncmp(p,
"WEBVTT"
, 6))
92
continue
;
93
94
/* optional cue identifier (can be a number like in SRT or some kind of
95
* chaptering id), silently skip it */
96
for
(i = 0; p[i] && p[i] !=
'\n'
; i++) {
97
if
(!strncmp(p + i,
"-->"
, 3)) {
98
identifier =
NULL
;
99
break
;
100
}
101
}
102
if
(identifier)
103
p += strcspn(p,
"\n"
);
104
105
/* cue timestamps */
106
if
((ts_start =
read_ts
(p)) ==
AV_NOPTS_VALUE
)
107
break
;
108
if
(!(p = strstr(p,
"-->"
)))
109
break
;
110
p += 3;
111
do
p++;
while
(*p ==
' '
|| *p ==
'\t'
);
112
if
((ts_end =
read_ts
(p)) ==
AV_NOPTS_VALUE
)
113
break
;
114
115
/* optional cue settings, TODO: store in side_data */
116
p += strcspn(p,
"\n\t "
);
117
while
(*p ==
'\t'
|| *p ==
' '
)
118
p++;
119
if
(*p !=
'\n'
) {
120
//settings = p;
121
p += strcspn(p,
"\n"
);
122
}
123
if
(*p ==
'\n'
)
124
p++;
125
126
/* create packet */
127
sub =
ff_subtitles_queue_insert
(&webvtt->
q
, p, strlen(p), 0);
128
if
(!sub) {
129
res =
AVERROR
(ENOMEM);
130
goto
end
;
131
}
132
sub->
pos
= pos;
133
sub->
pts
= ts_start;
134
sub->
duration
= ts_end - ts_start;
135
}
136
137
ff_subtitles_queue_finalize
(&webvtt->
q
);
138
139
end
:
140
av_bprint_finalize
(&cue,
NULL
);
141
av_bprint_finalize
(&header,
NULL
);
142
return
res;
143
}
144
145
static
int
webvtt_read_packet
(
AVFormatContext
*s,
AVPacket
*
pkt
)
146
{
147
WebVTTContext
*webvtt = s->
priv_data
;
148
return
ff_subtitles_queue_read_packet
(&webvtt->
q
, pkt);
149
}
150
151
static
int
webvtt_read_seek
(
AVFormatContext
*s,
int
stream_index,
152
int64_t min_ts, int64_t ts, int64_t max_ts,
int
flags
)
153
{
154
WebVTTContext
*webvtt = s->
priv_data
;
155
return
ff_subtitles_queue_seek
(&webvtt->
q
, s, stream_index,
156
min_ts, ts, max_ts, flags);
157
}
158
159
static
int
webvtt_read_close
(
AVFormatContext
*s)
160
{
161
WebVTTContext
*webvtt = s->
priv_data
;
162
ff_subtitles_queue_clean
(&webvtt->
q
);
163
return
0;
164
}
165
166
AVInputFormat
ff_webvtt_demuxer
= {
167
.
name
=
"webvtt"
,
168
.long_name =
NULL_IF_CONFIG_SMALL
(
"WebVTT subtitle"
),
169
.priv_data_size =
sizeof
(
WebVTTContext
),
170
.
read_probe
=
webvtt_probe
,
171
.
read_header
=
webvtt_read_header
,
172
.
read_packet
=
webvtt_read_packet
,
173
.read_seek2 =
webvtt_read_seek
,
174
.
read_close
=
webvtt_read_close
,
175
.extensions =
"vtt"
,
176
};
Generated on Sat May 25 2013 03:58:42 for FFmpeg by
1.8.2