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