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
jacosubdec.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
* JACOsub subtitle decoder
24
* @see http://unicorn.us.com/jacosub/jscripts.html
25
*/
26
27
#include <
time.h
>
28
#include "
ass.h
"
29
#include "
jacosub.h
"
30
#include "
libavutil/avstring.h
"
31
#include "
libavutil/bprint.h
"
32
33
#undef time
34
35
static
int
insert_text
(
AVBPrint
*dst,
const
char
*
in
,
const
char
*
arg
)
36
{
37
av_bprintf
(dst,
"%s"
, arg);
38
return
0;
39
}
40
41
static
int
insert_datetime
(
AVBPrint
*dst,
const
char
*
in
,
const
char
*
arg
)
42
{
43
char
buf
[16] = {0};
44
time_t now = time(0);
45
struct
tm ltime;
46
47
#if HAVE_LOCALTIME_R
48
localtime_r
(&now, <ime);
49
#else
50
ltime = *localtime(&now);
51
#endif
52
strftime(buf,
sizeof
(buf), arg, <ime);
53
av_bprintf
(dst,
"%s"
, buf);
54
return
0;
55
}
56
57
static
int
insert_color
(
AVBPrint
*dst,
const
char
*
in
,
const
char
*
arg
)
58
{
59
return
1;
// skip id
60
}
61
62
static
int
insert_font
(
AVBPrint
*dst,
const
char
*
in
,
const
char
*
arg
)
63
{
64
return
1;
// skip id
65
}
66
67
static
const
struct
{
68
const
char
*
from
;
69
const
char
*
arg
;
70
int (*
func
)(
AVBPrint
*dst,
const
char
*
in
,
const
char
*
arg
);
71
}
ass_codes_map
[] = {
72
{
"\\~"
,
"~"
,
insert_text
},
// tilde doesn't need escaping
73
{
"~"
,
"{\\h}"
,
insert_text
},
// hard space
74
{
"\\n"
,
"\\N"
,
insert_text
},
// newline
75
{
"\\D"
,
"%d %b %Y"
,
insert_datetime
},
// current date
76
{
"\\T"
,
"%H:%M"
,
insert_datetime
},
// current time
77
{
"\\N"
,
"{\\r}"
,
insert_text
},
// reset to default style
78
{
"\\I"
,
"{\\i1}"
,
insert_text
},
// italic on
79
{
"\\i"
,
"{\\i0}"
,
insert_text
},
// italic off
80
{
"\\B"
,
"{\\b1}"
,
insert_text
},
// bold on
81
{
"\\b"
,
"{\\b0}"
,
insert_text
},
// bold off
82
{
"\\U"
,
"{\\u1}"
,
insert_text
},
// underline on
83
{
"\\u"
,
"{\\u0}"
,
insert_text
},
// underline off
84
{
"\\C"
,
""
,
insert_color
},
// TODO: color
85
{
"\\F"
,
""
,
insert_font
},
// TODO: font
86
};
87
88
enum
{
89
ALIGN_VB
= 1<<0,
// vertical bottom, default
90
ALIGN_VM
= 1<<1,
// vertical middle
91
ALIGN_VT
= 1<<2,
// vertical top
92
ALIGN_JC
= 1<<3,
// justify center, default
93
ALIGN_JL
= 1<<4,
// justify left
94
ALIGN_JR
= 1<<5,
// justify right
95
};
96
97
static
void
jacosub_to_ass
(
AVCodecContext
*avctx,
AVBPrint
*dst,
const
char
*
src
)
98
{
99
int
i, valign = 0, halign = 0;
100
char
c
=
av_toupper
(*src);
101
char
directives[128] = {0};
102
103
/* extract the optional directives */
104
if
((c >=
'A'
&& c <=
'Z'
) || c ==
'['
) {
105
char
*p = directives;
106
char
*pend = directives +
sizeof
(directives) - 1;
107
108
do
*p++ =
av_toupper
(*src++);
109
while
(*src && !
jss_whitespace
(*src) && p < pend);
110
*p = 0;
111
src =
jss_skip_whitespace
(src);
112
}
113
114
/* handle directives (TODO: handle more of them, and more reliably) */
115
if
(strstr(directives,
"VB"
)) valign =
ALIGN_VB
;
116
else
if
(strstr(directives,
"VM"
)) valign =
ALIGN_VM
;
117
else
if
(strstr(directives,
"VT"
)) valign =
ALIGN_VT
;
118
if
(strstr(directives,
"JC"
)) halign =
ALIGN_JC
;
119
else
if
(strstr(directives,
"JL"
)) halign =
ALIGN_JL
;
120
else
if
(strstr(directives,
"JR"
)) halign =
ALIGN_JR
;
121
if
(valign || halign) {
122
if
(!valign) valign =
ALIGN_VB
;
123
if
(!halign) halign =
ALIGN_JC
;
124
switch
(valign | halign) {
125
case
ALIGN_VB
|
ALIGN_JL
:
av_bprintf
(dst,
"{\\an1}"
);
break
;
// bottom left
126
case
ALIGN_VB
|
ALIGN_JC
:
av_bprintf
(dst,
"{\\an2}"
);
break
;
// bottom center
127
case
ALIGN_VB
|
ALIGN_JR
:
av_bprintf
(dst,
"{\\an3}"
);
break
;
// bottom right
128
case
ALIGN_VM
|
ALIGN_JL
:
av_bprintf
(dst,
"{\\an4}"
);
break
;
// middle left
129
case
ALIGN_VM
|
ALIGN_JC
:
av_bprintf
(dst,
"{\\an5}"
);
break
;
// middle center
130
case
ALIGN_VM
|
ALIGN_JR
:
av_bprintf
(dst,
"{\\an6}"
);
break
;
// middle right
131
case
ALIGN_VT
|
ALIGN_JL
:
av_bprintf
(dst,
"{\\an7}"
);
break
;
// top left
132
case
ALIGN_VT
|
ALIGN_JC
:
av_bprintf
(dst,
"{\\an8}"
);
break
;
// top center
133
case
ALIGN_VT
|
ALIGN_JR
:
av_bprintf
(dst,
"{\\an9}"
);
break
;
// top right
134
}
135
}
136
137
/* process timed line */
138
while
(*src && *src !=
'\n'
) {
139
140
/* text continue on the next line */
141
if
(src[0] ==
'\\'
&& src[1] ==
'\n'
) {
142
src += 2;
143
while
(
jss_whitespace
(*src))
144
src++;
145
continue
;
146
}
147
148
/* special character codes */
149
for
(i = 0; i <
FF_ARRAY_ELEMS
(
ass_codes_map
); i++) {
150
const
char
*
from
=
ass_codes_map
[i].from;
151
const
char
*
arg
=
ass_codes_map
[i].arg;
152
size_t
codemap_len = strlen(from);
153
154
if
(!strncmp(src, from, codemap_len)) {
155
src += codemap_len;
156
src +=
ass_codes_map
[i].func(dst, src, arg);
157
break
;
158
}
159
}
160
161
/* simple char copy */
162
if
(i ==
FF_ARRAY_ELEMS
(
ass_codes_map
))
163
av_bprintf
(dst,
"%c"
, *src++);
164
}
165
av_bprintf
(dst,
"\r\n"
);
166
}
167
168
static
int
jacosub_decode_frame
(
AVCodecContext
*avctx,
169
void
*
data
,
int
*got_sub_ptr,
AVPacket
*avpkt)
170
{
171
AVSubtitle
*sub =
data
;
172
const
char
*ptr = avpkt->
data
;
173
174
if
(avpkt->
size
<= 0)
175
goto
end
;
176
177
if
(*ptr) {
178
AVBPrint
buffer
;
179
char
*dec_sub;
180
181
// skip timers
182
ptr =
jss_skip_whitespace
(ptr);
183
ptr = strchr(ptr,
' '
);
if
(!ptr)
goto
end
; ptr++;
184
ptr = strchr(ptr,
' '
);
if
(!ptr)
goto
end
; ptr++;
185
186
av_bprint_init
(&buffer,
JSS_MAX_LINESIZE
,
JSS_MAX_LINESIZE
);
187
jacosub_to_ass
(avctx, &buffer, ptr);
188
av_bprint_finalize
(&buffer, &dec_sub);
189
ff_ass_add_rect
(sub, dec_sub, avpkt->
pts
, avpkt->
duration
, 0);
190
av_free
(dec_sub);
191
}
192
193
end
:
194
*got_sub_ptr = sub->
num_rects
> 0;
195
return
avpkt->
size
;
196
}
197
198
AVCodec
ff_jacosub_decoder
= {
199
.
name
=
"jacosub"
,
200
.long_name =
NULL_IF_CONFIG_SMALL
(
"JACOsub subtitle"
),
201
.type =
AVMEDIA_TYPE_SUBTITLE
,
202
.id =
AV_CODEC_ID_JACOSUB
,
203
.init =
ff_ass_subtitle_header_default
,
204
.decode =
jacosub_decode_frame
,
205
};
Generated on Sun Mar 23 2014 23:49:57 for FFmpeg by
1.8.2