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
srtenc.c
Go to the documentation of this file.
1
/*
2
* SubRip subtitle encoder
3
* Copyright (c) 2010 Aurelien Jacobs <aurel@gnuage.org>
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
22
#include <stdarg.h>
23
#include "
avcodec.h
"
24
#include "
libavutil/avstring.h
"
25
#include "
libavutil/bprint.h
"
26
#include "
ass_split.h
"
27
#include "
ass.h
"
28
29
30
#define SRT_STACK_SIZE 64
31
32
typedef
struct
{
33
AVCodecContext
*
avctx
;
34
ASSSplitContext
*
ass_ctx
;
35
AVBPrint
buffer
;
36
char
stack[
SRT_STACK_SIZE
];
37
int
stack_ptr
;
38
int
alignment_applied
;
39
}
SRTContext
;
40
41
42
#ifdef __GNUC__
43
__attribute__ ((__format__ (__printf__, 2, 3)))
44
#endif
45
static
void
srt_print
(
SRTContext
*
s
,
const
char
*str, ...)
46
{
47
va_list vargs;
48
va_start(vargs, str);
49
av_vbprintf
(&s->
buffer
, str, vargs);
50
va_end(vargs);
51
}
52
53
static
int
srt_stack_push
(
SRTContext
*
s
,
const
char
c
)
54
{
55
if
(s->
stack_ptr
>=
SRT_STACK_SIZE
)
56
return
-1;
57
s->
stack
[s->
stack_ptr
++] =
c
;
58
return
0;
59
}
60
61
static
char
srt_stack_pop
(
SRTContext
*
s
)
62
{
63
if
(s->
stack_ptr
<= 0)
64
return
0;
65
return
s->
stack
[--s->
stack_ptr
];
66
}
67
68
static
int
srt_stack_find
(
SRTContext
*
s
,
const
char
c
)
69
{
70
int
i;
71
for
(i = s->
stack_ptr
-1; i >= 0; i--)
72
if
(s->
stack
[i] == c)
73
break
;
74
return
i;
75
}
76
77
static
void
srt_close_tag
(
SRTContext
*
s
,
char
tag
)
78
{
79
srt_print
(s,
"</%c%s>"
, tag, tag ==
'f'
?
"ont"
:
""
);
80
}
81
82
static
void
srt_stack_push_pop
(
SRTContext
*
s
,
const
char
c
,
int
close)
83
{
84
if
(close) {
85
int
i = c ?
srt_stack_find
(s, c) : 0;
86
if
(i < 0)
87
return
;
88
while
(s->
stack_ptr
!= i)
89
srt_close_tag
(s,
srt_stack_pop
(s));
90
}
else
if
(
srt_stack_push
(s, c) < 0)
91
av_log
(s->
avctx
,
AV_LOG_ERROR
,
"tag stack overflow\n"
);
92
}
93
94
static
void
srt_style_apply
(
SRTContext
*
s
,
const
char
*style)
95
{
96
ASSStyle
*st =
ff_ass_style_get
(s->
ass_ctx
, style);
97
if
(st) {
98
int
c
= st->
primary_color
& 0xFFFFFF;
99
if
(st->
font_name
&& strcmp(st->
font_name
,
ASS_DEFAULT_FONT
) ||
100
st->
font_size
!=
ASS_DEFAULT_FONT_SIZE
||
101
c !=
ASS_DEFAULT_COLOR
) {
102
srt_print
(s,
"<font"
);
103
if
(st->
font_name
&& strcmp(st->
font_name
,
ASS_DEFAULT_FONT
))
104
srt_print
(s,
" face=\"%s\""
, st->
font_name
);
105
if
(st->
font_size
!=
ASS_DEFAULT_FONT_SIZE
)
106
srt_print
(s,
" size=\"%d\""
, st->
font_size
);
107
if
(c !=
ASS_DEFAULT_COLOR
)
108
srt_print
(s,
" color=\"#%06x\""
,
109
(c & 0xFF0000) >> 16 | c & 0xFF00 | (c & 0xFF) << 16);
110
srt_print
(s,
">"
);
111
srt_stack_push
(s,
'f'
);
112
}
113
if
(st->
bold
!=
ASS_DEFAULT_BOLD
) {
114
srt_print
(s,
"<b>"
);
115
srt_stack_push
(s,
'b'
);
116
}
117
if
(st->
italic
!=
ASS_DEFAULT_ITALIC
) {
118
srt_print
(s,
"<i>"
);
119
srt_stack_push
(s,
'i'
);
120
}
121
if
(st->
underline
!=
ASS_DEFAULT_UNDERLINE
) {
122
srt_print
(s,
"<u>"
);
123
srt_stack_push
(s,
'u'
);
124
}
125
if
(st->
alignment
!=
ASS_DEFAULT_ALIGNMENT
) {
126
srt_print
(s,
"{\\an%d}"
, st->
alignment
);
127
s->
alignment_applied
= 1;
128
}
129
}
130
}
131
132
133
static
av_cold
int
srt_encode_init
(
AVCodecContext
*avctx)
134
{
135
SRTContext
*
s
= avctx->
priv_data
;
136
s->
avctx
= avctx;
137
s->
ass_ctx
=
ff_ass_split
(avctx->
subtitle_header
);
138
av_bprint_init
(&s->
buffer
, 0,
AV_BPRINT_SIZE_UNLIMITED
);
139
return
s->
ass_ctx
? 0 :
AVERROR_INVALIDDATA
;
140
}
141
142
static
void
srt_text_cb
(
void
*priv,
const
char
*text,
int
len
)
143
{
144
SRTContext
*
s
= priv;
145
av_bprint_append_data
(&s->
buffer
, text, len);
146
}
147
148
static
void
srt_new_line_cb
(
void
*priv,
int
forced)
149
{
150
srt_print
(priv,
"\r\n"
);
151
}
152
153
static
void
srt_style_cb
(
void
*priv,
char
style,
int
close)
154
{
155
srt_stack_push_pop
(priv, style, close);
156
if
(!close)
157
srt_print
(priv,
"<%c>"
, style);
158
}
159
160
static
void
srt_color_cb
(
void
*priv,
unsigned
int
color
,
unsigned
int
color_id)
161
{
162
if
(color_id > 1)
163
return
;
164
srt_stack_push_pop
(priv,
'f'
, color == 0xFFFFFFFF);
165
if
(color != 0xFFFFFFFF)
166
srt_print
(priv,
"<font color=\"#%06x\">"
,
167
(color & 0xFF0000) >> 16 | color & 0xFF00 | (color & 0xFF) << 16);
168
}
169
170
static
void
srt_font_name_cb
(
void
*priv,
const
char
*
name
)
171
{
172
srt_stack_push_pop
(priv,
'f'
, !name);
173
if
(name)
174
srt_print
(priv,
"<font face=\"%s\">"
, name);
175
}
176
177
static
void
srt_font_size_cb
(
void
*priv,
int
size
)
178
{
179
srt_stack_push_pop
(priv,
'f'
, size < 0);
180
if
(size >= 0)
181
srt_print
(priv,
"<font size=\"%d\">"
, size);
182
}
183
184
static
void
srt_alignment_cb
(
void
*priv,
int
alignment)
185
{
186
SRTContext
*
s
= priv;
187
if
(!s->
alignment_applied
&& alignment >= 0) {
188
srt_print
(s,
"{\\an%d}"
, alignment);
189
s->
alignment_applied
= 1;
190
}
191
}
192
193
static
void
srt_cancel_overrides_cb
(
void
*priv,
const
char
*style)
194
{
195
srt_stack_push_pop
(priv, 0, 1);
196
srt_style_apply
(priv, style);
197
}
198
199
static
void
srt_move_cb
(
void
*priv,
int
x1,
int
y1,
int
x2,
int
y2,
200
int
t1
,
int
t2
)
201
{
202
// TODO: add a AV_PKT_DATA_SUBTITLE_POSITION side data when a new subtitles
203
// encoding API passing the AVPacket is available.
204
}
205
206
static
void
srt_end_cb
(
void
*priv)
207
{
208
srt_stack_push_pop
(priv, 0, 1);
209
}
210
211
static
const
ASSCodesCallbacks
srt_callbacks
= {
212
.
text
=
srt_text_cb
,
213
.new_line =
srt_new_line_cb
,
214
.style =
srt_style_cb
,
215
.color =
srt_color_cb
,
216
.font_name =
srt_font_name_cb
,
217
.font_size =
srt_font_size_cb
,
218
.alignment =
srt_alignment_cb
,
219
.cancel_overrides =
srt_cancel_overrides_cb
,
220
.move =
srt_move_cb
,
221
.end =
srt_end_cb
,
222
};
223
224
static
int
srt_encode_frame
(
AVCodecContext
*avctx,
225
unsigned
char
*
buf
,
int
bufsize,
const
AVSubtitle
*sub)
226
{
227
SRTContext
*
s
= avctx->
priv_data
;
228
ASSDialog
*dialog;
229
int
i, num;
230
231
av_bprint_clear
(&s->
buffer
);
232
233
for
(i=0; i<sub->
num_rects
; i++) {
234
235
if
(sub->
rects
[i]->
type
!=
SUBTITLE_ASS
) {
236
av_log
(avctx,
AV_LOG_ERROR
,
"Only SUBTITLE_ASS type supported.\n"
);
237
return
AVERROR
(ENOSYS);
238
}
239
240
dialog =
ff_ass_split_dialog
(s->
ass_ctx
, sub->
rects
[i]->
ass
, 0, &num);
241
for
(; dialog && num--; dialog++) {
242
s->
alignment_applied
= 0;
243
srt_style_apply
(s, dialog->
style
);
244
ff_ass_split_override_codes
(&srt_callbacks, s, dialog->
text
);
245
}
246
}
247
248
if
(!
av_bprint_is_complete
(&s->
buffer
))
249
return
AVERROR
(ENOMEM);
250
if
(!s->
buffer
.len)
251
return
0;
252
253
if
(s->
buffer
.len > bufsize) {
254
av_log
(avctx,
AV_LOG_ERROR
,
"Buffer too small for ASS event.\n"
);
255
return
-1;
256
}
257
memcpy(buf, s->
buffer
.str, s->
buffer
.len);
258
259
return
s->
buffer
.len;
260
}
261
262
static
int
srt_encode_close
(
AVCodecContext
*avctx)
263
{
264
SRTContext
*
s
= avctx->
priv_data
;
265
ff_ass_split_free
(s->
ass_ctx
);
266
av_bprint_finalize
(&s->
buffer
,
NULL
);
267
return
0;
268
}
269
270
#if CONFIG_SRT_ENCODER
271
/* deprecated encoder */
272
AVCodec
ff_srt_encoder = {
273
.
name
=
"srt"
,
274
.long_name =
NULL_IF_CONFIG_SMALL
(
"SubRip subtitle"
),
275
.type =
AVMEDIA_TYPE_SUBTITLE
,
276
.id =
AV_CODEC_ID_SUBRIP
,
277
.priv_data_size =
sizeof
(
SRTContext
),
278
.
init
=
srt_encode_init
,
279
.encode_sub =
srt_encode_frame
,
280
.close =
srt_encode_close
,
281
};
282
#endif
283
284
#if CONFIG_SUBRIP_ENCODER
285
AVCodec
ff_subrip_encoder = {
286
.
name
=
"subrip"
,
287
.long_name =
NULL_IF_CONFIG_SMALL
(
"SubRip subtitle"
),
288
.type =
AVMEDIA_TYPE_SUBTITLE
,
289
.id =
AV_CODEC_ID_SUBRIP
,
290
.priv_data_size =
sizeof
(
SRTContext
),
291
.
init
=
srt_encode_init
,
292
.encode_sub =
srt_encode_frame
,
293
.close =
srt_encode_close
,
294
};
295
#endif
Generated on Sun Mar 8 2015 02:35:00 for FFmpeg by
1.8.2