FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
•
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavcodec
webvttenc.c
Go to the documentation of this file.
1
/*
2
* WebVTT subtitle encoder
3
* Copyright (c) 2010 Aurelien Jacobs <aurel@gnuage.org>
4
* Copyright (c) 2014 Aman Gupta <ffmpeg@tmm1.net>
5
*
6
* This file is part of FFmpeg.
7
*
8
* FFmpeg is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public
10
* License as published by the Free Software Foundation; either
11
* version 2.1 of the License, or (at your option) any later version.
12
*
13
* FFmpeg is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
17
*
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with FFmpeg; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
*/
22
23
#include <stdarg.h>
24
#include "
avcodec.h
"
25
#include "
libavutil/avstring.h
"
26
#include "
libavutil/bprint.h
"
27
#include "
ass_split.h
"
28
#include "
ass.h
"
29
30
#define WEBVTT_STACK_SIZE 64
31
typedef
struct
{
32
AVCodecContext
*
avctx
;
33
ASSSplitContext
*
ass_ctx
;
34
AVBPrint
buffer
;
35
unsigned
timestamp_end
;
36
int
count
;
37
char
stack[
WEBVTT_STACK_SIZE
];
38
int
stack_ptr
;
39
}
WebVTTContext
;
40
41
#ifdef __GNUC__
42
__attribute__ ((__format__ (__printf__, 2, 3)))
43
#endif
44
static
void
webvtt_print
(
WebVTTContext
*
s
,
const
char
*str, ...)
45
{
46
va_list vargs;
47
va_start(vargs, str);
48
av_vbprintf
(&s->
buffer
, str, vargs);
49
va_end(vargs);
50
}
51
52
static
int
webvtt_stack_push
(
WebVTTContext
*
s
,
const
char
c
)
53
{
54
if
(s->
stack_ptr
>=
WEBVTT_STACK_SIZE
)
55
return
-1;
56
s->
stack
[s->
stack_ptr
++] =
c
;
57
return
0;
58
}
59
60
static
char
webvtt_stack_pop
(
WebVTTContext
*
s
)
61
{
62
if
(s->
stack_ptr
<= 0)
63
return
0;
64
return
s->
stack
[--s->
stack_ptr
];
65
}
66
67
static
int
webvtt_stack_find
(
WebVTTContext
*
s
,
const
char
c
)
68
{
69
int
i;
70
for
(i = s->
stack_ptr
-1; i >= 0; i--)
71
if
(s->
stack
[i] == c)
72
break
;
73
return
i;
74
}
75
76
static
void
webvtt_close_tag
(
WebVTTContext
*
s
,
char
tag
)
77
{
78
webvtt_print
(s,
"</%c>"
, tag);
79
}
80
81
static
void
webvtt_stack_push_pop
(
WebVTTContext
*
s
,
const
char
c
,
int
close
)
82
{
83
if
(close) {
84
int
i = c ?
webvtt_stack_find
(s, c) : 0;
85
if
(i < 0)
86
return
;
87
while
(s->
stack_ptr
!= i)
88
webvtt_close_tag
(s,
webvtt_stack_pop
(s));
89
}
else
if
(
webvtt_stack_push
(s, c) < 0)
90
av_log
(s->
avctx
,
AV_LOG_ERROR
,
"tag stack overflow\n"
);
91
}
92
93
static
void
webvtt_style_apply
(
WebVTTContext
*
s
,
const
char
*style)
94
{
95
ASSStyle
*st =
ff_ass_style_get
(s->
ass_ctx
, style);
96
if
(st) {
97
if
(st->
bold
!=
ASS_DEFAULT_BOLD
) {
98
webvtt_print
(s,
"<b>"
);
99
webvtt_stack_push
(s,
'b'
);
100
}
101
if
(st->
italic
!=
ASS_DEFAULT_ITALIC
) {
102
webvtt_print
(s,
"<i>"
);
103
webvtt_stack_push
(s,
'i'
);
104
}
105
if
(st->
underline
!=
ASS_DEFAULT_UNDERLINE
) {
106
webvtt_print
(s,
"<u>"
);
107
webvtt_stack_push
(s,
'u'
);
108
}
109
}
110
}
111
112
static
void
webvtt_text_cb
(
void
*priv,
const
char
*text,
int
len
)
113
{
114
WebVTTContext
*
s
= priv;
115
av_bprint_append_data
(&s->
buffer
, text, len);
116
}
117
118
static
void
webvtt_new_line_cb
(
void
*priv,
int
forced)
119
{
120
webvtt_print
(priv,
"\n"
);
121
}
122
123
static
void
webvtt_style_cb
(
void
*priv,
char
style,
int
close
)
124
{
125
if
(style ==
's'
)
// strikethrough unsupported
126
return
;
127
128
webvtt_stack_push_pop
(priv, style, close);
129
if
(!close)
130
webvtt_print
(priv,
"<%c>"
, style);
131
}
132
133
static
void
webvtt_cancel_overrides_cb
(
void
*priv,
const
char
*style)
134
{
135
webvtt_stack_push_pop
(priv, 0, 1);
136
webvtt_style_apply
(priv, style);
137
}
138
139
static
void
webvtt_end_cb
(
void
*priv)
140
{
141
webvtt_stack_push_pop
(priv, 0, 1);
142
}
143
144
static
const
ASSCodesCallbacks
webvtt_callbacks
= {
145
.
text
=
webvtt_text_cb
,
146
.new_line =
webvtt_new_line_cb
,
147
.style =
webvtt_style_cb
,
148
.color = NULL,
149
.font_name = NULL,
150
.font_size = NULL,
151
.alignment = NULL,
152
.cancel_overrides =
webvtt_cancel_overrides_cb
,
153
.move = NULL,
154
.end =
webvtt_end_cb
,
155
};
156
157
static
int
webvtt_encode_frame
(
AVCodecContext
*avctx,
158
unsigned
char
*
buf
,
int
bufsize,
const
AVSubtitle
*sub)
159
{
160
WebVTTContext
*
s
= avctx->
priv_data
;
161
ASSDialog
*dialog;
162
int
i, num;
163
164
av_bprint_clear
(&s->
buffer
);
165
166
for
(i=0; i<sub->
num_rects
; i++) {
167
if
(sub->
rects
[i]->
type
!=
SUBTITLE_ASS
) {
168
av_log
(avctx,
AV_LOG_ERROR
,
"Only SUBTITLE_ASS type supported.\n"
);
169
return
AVERROR
(ENOSYS);
170
}
171
172
dialog =
ff_ass_split_dialog
(s->
ass_ctx
, sub->
rects
[i]->
ass
, 0, &num);
173
for
(; dialog && num--; dialog++) {
174
webvtt_style_apply
(s, dialog->
style
);
175
ff_ass_split_override_codes
(&webvtt_callbacks, s, dialog->
text
);
176
}
177
}
178
179
if
(!
av_bprint_is_complete
(&s->
buffer
))
180
return
AVERROR
(ENOMEM);
181
if
(!s->
buffer
.len)
182
return
0;
183
184
if
(s->
buffer
.len > bufsize) {
185
av_log
(avctx,
AV_LOG_ERROR
,
"Buffer too small for ASS event.\n"
);
186
return
-1;
187
}
188
memcpy(buf, s->
buffer
.str, s->
buffer
.len);
189
190
return
s->
buffer
.len;
191
}
192
193
static
int
webvtt_encode_close
(
AVCodecContext
*avctx)
194
{
195
WebVTTContext
*
s
= avctx->
priv_data
;
196
ff_ass_split_free
(s->
ass_ctx
);
197
av_bprint_finalize
(&s->
buffer
, NULL);
198
return
0;
199
}
200
201
static
av_cold
int
webvtt_encode_init
(
AVCodecContext
*avctx)
202
{
203
WebVTTContext
*
s
= avctx->
priv_data
;
204
s->
avctx
= avctx;
205
s->
ass_ctx
=
ff_ass_split
(avctx->
subtitle_header
);
206
av_bprint_init
(&s->
buffer
, 0,
AV_BPRINT_SIZE_UNLIMITED
);
207
return
s->
ass_ctx
? 0 :
AVERROR_INVALIDDATA
;
208
}
209
210
AVCodec
ff_webvtt_encoder
= {
211
.
name
=
"webvtt"
,
212
.long_name =
NULL_IF_CONFIG_SMALL
(
"WebVTT subtitle"
),
213
.type =
AVMEDIA_TYPE_SUBTITLE
,
214
.id =
AV_CODEC_ID_WEBVTT
,
215
.priv_data_size =
sizeof
(
WebVTTContext
),
216
.
init
=
webvtt_encode_init
,
217
.encode_sub =
webvtt_encode_frame
,
218
.
close
=
webvtt_encode_close
,
219
};
Generated on Sun Jul 20 2014 23:05:58 for FFmpeg by
1.8.2